<template>
  <div>
    <el-table
      v-bind="$attrs"
      :data="tableData"
      v-loading="isLoading"
      :element-loading-text="elementLoadingText"
      :element-loading-spinner="elementLoadingSpinner"
      :element-loading-svg-view-box="elementLoadingSvgViewBox"
      :element-loading-background="elementLoadingBackground"
      @row-click="rowClick"
    >
      <template v-for="(item, index) in tableOptions" :key="index">
        <el-table-column
          :prop="item.prop"
          :label="item.label"
          :width="item.width"
          :align="item.align"
        >
          <template #default="scope">
            <template v-if="scope.row.rowEdit">
              <el-input v-model="scope.row[item.prop]" size="small"></el-input>
            </template>
            <template v-else>
              <template v-if="scope.$index + scope.column.id == currentEdit">
                <div class="input-div">
                  <el-input
                    type="small"
                    v-model="scope.row[item.prop]"
                  ></el-input>
                  <div @click.stop="clickEditCell">
                    <slot
                      name="editCell"
                      v-if="$slots.editCell"
                      :scope="scope"
                    ></slot>
                    <!-- 确认和取消 -->
                    <div class="icons" v-else>
                      <el-icon-check
                        class="check"
                        @click="check(scope)"
                      ></el-icon-check>
                      <el-icon-close
                        class="close"
                        @click="close(scope)"
                      ></el-icon-close>
                    </div>
                  </div>
                </div>
              </template>
              <template v-else>
                <slot v-if="item.slot" :name="item.slot" :scope="scope"></slot>
                <span v-else>{{ scope.row[item.prop] }}</span>
                <!-- 可编辑单元格 -->
                <component
                  :is="`el-icon-${toLine(editIcon)}`"
                  @click.stop="clickEdit(scope)"
                  v-if="item.editable"
                  class="edit"
                ></component>
              </template>
            </template>
          </template>
        </el-table-column>
      </template>
      <!-- 操作项 -->
      <el-table-column
        :prop="actionOptions!.prop"
        :label="actionOptions!.label"
        :width="actionOptions!.width"
        :align="actionOptions!.align"
      >
        <template #default="scope">
          <slot name="editRow" v-if="scope.row.rowEdit" :scope="scope"></slot>
          <slot name="action" v-else :scope="scope"></slot>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页 -->
    <div
      class="pagination"
      v-if="showPagination"
      :style="{ justifyContent: paginationAlignJustify }"
    >
      <el-pagination
        v-model:current-page="currentPage"
        v-model:page-size="pageSize"
        :page-sizes="pageSizes"
        :small="small"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, PropType, computed, onMounted, watch } from "vue";
import { TableOptions } from "./types";
import { toLine } from "../../../utils/index";
import cloneDeep from "lodash/cloneDeep";
/*************************data*******************************/
let props = defineProps({
  // 表格配置
  options: {
    type: Array as PropType<TableOptions[]>,
    require: true,
  },
  // 表格数据
  data: {
    type: Array as PropType<any[]>,
    require: true,
  },
  // loading文字加载文字
  elementLoadingText: {
    type: String,
  },
  // loading加载图标
  elementLoadingSpinner: {
    type: String,
  },
  // loading加载svg
  elementLoadingSvg: {
    type: String,
  },
  // loading加载svg的配置
  elementLoadingSvgViewBox: {
    type: String,
  },
  // loading背景颜色
  elementLoadingBackground: {
    type: String,
  },
  // 可编辑单元格显示的图标
  editIcon: {
    type: String,
    default: "edit",
  },
  // 是否可以编辑行
  isEditRow: {
    type: Boolean,
    default: false,
  },
  // 编辑行按钮的标识
  editRowIndex: {
    type: String,
    default: "",
  },
  // 分页配置
  currentPage: {
    type: Number,
    default: 1,
  },
  pageSizes: {
    type: Array as PropType<number[]>,
    default: [5, 10, 20, 40, 50],
  },
  pageSize: {
    type: Number,
    default: 5,
  },
  total: {
    type: Number,
    default: 0,
  },
  small: {
    type: Boolean,
    default: false,
  },
  showPagination: {
    type: Boolean,
    default: false,
  },
  // 分页的排列方式
  paginationAlign: {
    type: String as PropType<"left" | "center" | "right">,
    default: "right",
  },
});
// 当前点击的单元格
let currentEdit = ref<string>("");
// 找出非操作项的配置
let tableOptions = computed(() =>
  props.options?.filter((item) => !item.action)
);
// 找出操作项的配置
let actionOptions = computed(() => props.options?.find((item) => item.action));
// 表格数据不存在时，加载loading
let isLoading = computed(() => !props.data || !props.data.length);

/*************************method*******************************/
let emits = defineEmits([
  "check",
  "close",
  "update:editRowIndex",
  "sizeChange",
  "currentChange",
]);
let clickEdit = (scope: any) => {
  // 唯一的标识
  currentEdit.value = scope.$index + scope.column.id;
};
// 取消编辑
const clickEditCell = () => {
  currentEdit.value = "";
};

// 拷贝表格的数据
let tableData = ref<any>(cloneDeep(props.data));

// 拷贝按钮的标识
let cloneEditRowIndex = ref<string>(props.editRowIndex);

// 监听父组件传过来的数据
watch(
  () => props.data,
  (val) => {
    tableData.value = cloneDeep(val);
    tableData.value.map((item: { rowEdit: boolean }) => {
      // 代表当前是否是可编辑的状态
      item.rowEdit = false;
    });
  },
  { deep: true }
);
// 监听父组件传过来的标识
watch(
  () => props.editRowIndex,
  (val) => {
    if (val) cloneEditRowIndex.value = val;
  }
);
onMounted(() => {
  tableData.value.map((item: { rowEdit: boolean }) => {
    // 代表当前是否是可编辑的状态
    item.rowEdit = false;
  });
});

// 点击每一行的事件
const rowClick = (row: any, column: any) => {
  console.log(column);

  // 判断当前点击的是否是操作项的内容
  if (column.label == actionOptions.value?.label) {
    // 编辑行的操作
    if (props.isEditRow && cloneEditRowIndex.value === props.editRowIndex) {
      // 点击的按钮是做可编辑的操作
      row.rowEdit = !row.rowEdit;
      // 重置其他数据的isEditRow
      tableData.value.map((item) => {
        if (item !== row) item.rowEdit = false;
      });
      // 要重置按钮的标识
      if (!row.rowEdit) emits("update:editRowIndex", "");
    }
  }
};

// 编辑行--保存
const check = (scope: any) => {
  emits("check", scope);
};

// 编辑行--删除
const close = (scope: any) => {
  emits("close", scope);
};

// 分页的页数改变
const handleCurrentChange = (val: number) => {
  emits("sizeChange", val);
};
// 分页的条数改变
const handleSizeChange = (val: number) => {
  emits("currentChange", val);
};
// 分页的排列方式
let paginationAlignJustify = computed(() => {
  if (props.paginationAlign == "left") {
    return "flex-start";
  } else if (props.paginationAlign == "center") {
    return "center";
  } else return "flex-end";
});
</script>
<style lang="scss" scoped>
.edit {
  width: 1em;
  height: 1em;
  position: relative;
  top: 2px;
  left: 4px;
  cursor: pointer;
}
.input-div {
  display: flex;
  .icons {
    display: flex;
    position: relative;
    top: 6px;
    svg {
      cursor: pointer;
      width: 1em;
      height: 1em;
      margin-left: 8px;
    }
    .check {
      color: green;
    }
    .close {
      color: red;
    }
  }
}
.pagination {
  display: flex;
  justify-content: flex-end;
  margin-top: 16px;
}
</style>
